package deepbitview

/**
 * used to generate basic graphs
 */
class GraphController {

    def index = { }

    DifficultyService difficultyService

    /**
     * renders a simple graph showing  a bar chart of stales vs shares
     */
    def ajaxShowWorkerStaleShareRatio = {

        def data = [:]

        def label = [:]

        //building the dataset
        Worker.list().eachWithIndex {Worker worker, int index ->

            data[worker.name] = [worker.stales/worker.shares * 100]

            label[index] = ""
        }

        render(template: "barChart", model: [data: data, label: label, title: "percent of stale files for each worker", id: "worker_shares_stales_${System.currentTimeMillis()}", height: 320, width: 480])
    }

    /**
     * shows the network speed for the given timeframe
     */
    def ajaxShowNetworkSpeed = {

        def days = (params.day != null) ? Integer.parseInt(params.day) : 1

        def data = [:]
        def label = [:]

        (data, label) = calculateLineChartData("Thash/s", days, {Sample sample, int counter ->
            return sample.globalNetworkSpeed
        })

        render(template: "lineChart", model: [data: data, label: label, title: "network speed for the last ${days} days", id: "show_network_speeds_${System.currentTimeMillis()}", height: 320, width: 480])
    }

    /**
     * shows the network speed for the given timeframe
     */
    def ajaxShowExchangeRate = {

        def days = (params.day != null) ? Integer.parseInt(params.day) : 1

        def data = [:]
        def label = [:]

        (data, label) = calculateLineChartData("USD", days, {Sample sample, int counter ->
            return sample.exchangeRateUSD
        })

        render(template: "lineChart", model: [data: data, label: label, title: "exchange rate for the last ${days} days", id: "show_exchange_${System.currentTimeMillis()}", height: 320, width: 480])
    }

    /**
     * simple format for labels
     * @param counter
     * @param s
     * @param label
     * @param samples
     * @return
     */
    private def labelSetup(int counter, Sample s, LinkedHashMap label, List<Sample> samples) {

        String date = s.sampleTime.format('EEE, MMM d, yyyy')
        if (counter == 0) {
            label[0] = date
        }
        else if (counter == samples.size() - 1) {
            label[samples.size() - 1] = date
        }

        else {
            label[counter] = ""

        }
    }

    /**
     * shows the network speed for the given timeframe
     */
    def ajaxShowBlocks = {

        def days = (params.day != null) ? Integer.parseInt(params.day) : 1

        def data = null
        def label = null

        (data, label) = calculateLineChartData("Blocks", days, {Sample sample, int counter ->
            return sample.globalyKnownBlocks
        })

        render(template: "lineChart", model: [data: data, label: label, title: "globally known blocks for last ${days} days", id: "hash_rate_${System.currentTimeMillis()}", height: 320, width: 480])
    }

    /**
     * shows the network speed for the given timeframe
     */
    def ajaxShowAccountGraph = {

        def days = (params.day != null) ? Integer.parseInt(params.day) : 1

        def data = null
        def label = null

        (data, label) = calculateLineChartData("BitCoins", days, {Sample sample, int counter ->
            return sample.reward
        })

        render(template: "lineChart", model: [data: data, label: label, title: "account balance in the last ${days} days", id: "account_${System.currentTimeMillis()}", height: 320, width: 480])
    }

    /**
     * shows the network speed for the given timeframe
     */
    def ajaxShowAccountUSDGraph = {

        def days = (params.day != null) ? Integer.parseInt(params.day) : 1

        def data = null
        def label = null

        (data, label) = calculateLineChartData("USD", days, {Sample sample, int counter ->
            return sample.reward * sample.exchangeRateUSD
        })

        render(template: "lineChart", model: [data: data, label: label, title: "account balance in the last ${days} days", id: "account_${System.currentTimeMillis()}", height: 320, width: 480])
    }

    /**
     * shows the network speed for the given timeframe
     */
    def ajaxShowPerformanceGraph = {

        def days = (params.day != null) ? Integer.parseInt(params.day) : 1

        def data = null
        def label = null

        (data, label) = calculateLineChartData("Mhash/s", days, {Sample sample, int counter ->
            return sample.hashRate
        })

        render(template: "lineChart", model: [data: data, label: label, title: "hash rate for all workers for the last ${days} days", id: "hash_rate_${System.currentTimeMillis()}", height: 320, width: 480])
    }

    /**
     * shows the network speed for the given timeframe
     */
    def ajaxShowCoinsPerSampleGraph = {

        def days = (params.day != null) ? Integer.parseInt(params.day) : 1

        def data = null
        def label = null

        (data, label) = calculateLineChartData("coins", days, {Sample sample, int counter ->
            def result = difficultyService.calculateCoinsForMinute(sample.difficulty, sample.hashRate) * ActiviationKeyHandler.getSampleRateInMinutes()

            if (result >= 0) {
                return result
            }
            else {
                return 0
            }
        })

        render(template: "lineChart", model: [data: data, label: label, title: "coins generated for ${ActiviationKeyHandler.getSampleRateInMinutes()} minutes samples for the last ${days} days", id: "hash_rate_${System.currentTimeMillis()}", height: 320, width: 480])
    }

    /**
     * shows the network speed for the given timeframe
     */
    def ajaxShowDollarPerSampleGraph = {

        def days = (params.day != null) ? Integer.parseInt(params.day) : 1

        def data = null
        def label = null

        (data, label) = calculateLineChartData("USD", days, {Sample sample, int counter ->
            def result = difficultyService.calculateCoinsForMinute(sample.difficulty, sample.hashRate) * ActiviationKeyHandler.getSampleRateInMinutes() / sample.exchangeRateUSD

            if (result >= 0) {
                return result
            }
            else {
                return 0
            }
        })

        render(template: "lineChart", model: [data: data, label: label, title: "USD generated for ${ActiviationKeyHandler.getSampleRateInMinutes()} minutes samples for the last ${days} days", id: "hash_rate_${System.currentTimeMillis()}", height: 320, width: 480])
    }
    /**
     * calculates the linechart data over the selected dates
     * @param days
     * @return
     */
    private List calculateLineChartData(String key, int days, def closure) {
        def end = new Date()
        def begin = end - days

        def data = [:]
        def label = [:]

        def samples = Sample.findAllBySampleTimeBetween(begin, end)

        //sort our data
        samples.sort { Sample a, Sample b ->
            a.sampleTime.compareTo(b.sampleTime)
        }

        data[key] = []

        samples.eachWithIndex {Sample s, int counter ->

            def value = (closure(s, counter))
            if (value != TickerService.ERROR_CODE) {
                data[key].add(value)
                labelSetup(counter, s, label, samples)
            }
        }
        return [data, label]
    }

}
